package org.desktop.diskutils.components.treemap;

import java.io.IOException;

import org.desktop.diskutils.business.files.IFileTree;
import org.desktop.diskutils.business.files.IFileTreeNode;
import org.desktop.diskutils.business.files.ITreeNodeVisitor;

import prefuse.data.Node;
import prefuse.data.Table;
import prefuse.data.Tree;

public class TreeBuilder {

	public final static String LABEL_ATTR = "name"; // NOI18N;
	public final static String AREA_ATTR = "area"; // NOI18N;
	public final static String CATEGORY_NAME_ATTR = "ext"; // NOI18N;
	public static final String BUSINESS_TREE_NODE_ATTR = "businesstreenode"; // NOI18N;

	final private IFileTree fileTree;

	public TreeBuilder(final IFileTree tree) {
		this.fileTree = tree;
	}

	public Tree buildTree() throws IOException {
		TreeBuilderMapVisitor visitor = new TreeBuilderMapVisitor();
		fileTree.getRoot().visitDisplayedNodes(visitor);
		return visitor.getTree();
	}

	private class TreeBuilderMapVisitor implements ITreeNodeVisitor {
		private Tree tree;
		private Table nodeTable;
		private Node activeNode = null;

		public TreeBuilderMapVisitor() {
			tree = new Tree();
			nodeTable = tree.getNodeTable();
			nodeTable.addColumn(LABEL_ATTR, String.class);
			nodeTable.addColumn(AREA_ATTR, Double.class);
			nodeTable.addColumn(CATEGORY_NAME_ATTR, String.class);
			nodeTable.addColumn(BUSINESS_TREE_NODE_ATTR, IFileTreeNode.class);
		}

		@Override
		public void visit(IFileTreeNode node) {
			if (node.getChildren().isEmpty()) {
				Node n = tree.addChild(activeNode);
				n.set(AREA_ATTR, (double) node.getSize());
				n.set(LABEL_ATTR, node.getName());
				n.set(CATEGORY_NAME_ATTR, node.getCategoryName());
				n.set(BUSINESS_TREE_NODE_ATTR, node);
			}
		}

		@Override
		public void preVisitBranchNode(IFileTreeNode branchNode) {
			if (activeNode == null) {
				activeNode = tree.addRoot();
			} else {
				activeNode = tree.addChild(activeNode);
			}
			activeNode.set(LABEL_ATTR, branchNode.getName());
			activeNode.set(AREA_ATTR, (double) branchNode.getSize());
			activeNode.set(CATEGORY_NAME_ATTR, branchNode.getCategoryName());
			activeNode.set(BUSINESS_TREE_NODE_ATTR, branchNode);
		}

		@Override
		public void postVisitBranchNode(IFileTreeNode branchNode) {
			activeNode = activeNode.getParent();
		}

		public Tree getTree() {
			return tree;
		}
	}

}
